'use client';

import {
  type ChangeEvent,
  type FormEvent,
  useContext,
  useEffect,
  useState,
} from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import diff from 'microdiff';
import type {
  IConfigOauthClient,
  IDifference,
  IUpdateOauthClientConfigBody,
  IYwOauthClient,
} from '@/interfaces';
import type { TBody } from '@/types';
import { updateOauthClientConfig } from '@/services/api';
import classNames from 'classnames';
import useToast from '@/hooks/useToast';
import { nanoid } from 'nanoid';
import { ConfigAdminContext } from '@/contexts/admin/config';
import { getDiffData, getFilterData, isEmpty } from '@/lib/tool';

export default function UpdateConfigOauthClient(
  this: any,
  {
    details,
  }: {
    details: IConfigOauthClient;
  },
) {
  const { show } = useToast();
  const [form, setForm] = useState<{
    showMenuEntry: boolean;
    doc?: string;
  }>({
    showMenuEntry: true,
    doc: '',
  });
  const [clients, setClients] = useState<IYwOauthClient[]>([]);
  const [clientForm, setClientForm] = useState<IYwOauthClient>({
    enable: false,
    clientId: '',
    clientSecret: '',
    redirectUri: '',
    scope: '',
    state: '',
    clientName: '',
    clientSite: '',
    clientLogo: '',
    imagePathPrefix: '',
    remark: '',
  });
  const [differenceData, setDifferenceData] = useState<IDifference[]>([]);
  const queryClient = useQueryClient();
  const [tabIndex, setTabIndex] = useState(0);
  const [currentClientItem, setCurrentClientItem] = useState<IYwOauthClient>();
  const context = useContext(ConfigAdminContext);

  const updateOauthClientConfigMutation = useMutation(
    async (variables: TBody<IUpdateOauthClientConfigBody>) => {
      await updateOauthClientConfig(variables);
      await queryClient.refetchQueries(
        ['/configs', `/${context.updateItem?.id}`],
        {},
        { throwOnError: true },
      );
    },
  );

  useEffect(() => {
    if (details) {
      setForm({
        showMenuEntry: details.showMenuEntry,
        doc: details.doc || '',
      });
      setClients(details.ywClients);
    }
  }, [details]);
  useEffect(() => {
    if (details) {
      const differences = diff(
        {
          showMenuEntry: details.showMenuEntry,
          doc: details.doc || '',
          ywClients: details.ywClients,
        },
        {
          showMenuEntry: form.showMenuEntry,
          doc: form.doc,
          ywClients: clients,
        },
      );
      setDifferenceData(differences);
    }
  }, [form, clients, details]);

  function onClickTab(index: number) {
    setTabIndex(index);
  }

  function onClickSaveItem() {
    const { clientId, redirectUri } = clientForm;
    if (!clientId) {
      show({
        type: 'DANGER',
        message: '客户端 Id 不能为空',
      });
      return;
    } else if (clients.find((item) => item.clientId === clientId)) {
      show({
        type: 'DANGER',
        message: '该客户端 Id 已经存在列表中',
      });
      return;
    }

    if (!redirectUri) {
      show({
        type: 'DANGER',
        message: '重定向地址不能为空',
      });
      return;
    }

    let scope = clientForm.scope;
    if (!scope) {
      scope = 'getUserInfo';
    }

    let state = clientForm.state;
    if (!state) {
      state = nanoid();
    }

    let clientSecret = clientForm.clientSecret;
    if (!clientSecret) {
      clientSecret = nanoid();
    }

    setClients([
      ...clients,
      {
        ...clientForm,
        clientSecret,
        scope,
        state,
      },
    ]);

    show({
      type: 'PRIMARY',
      message: '添加到列表完成',
    });
  }

  function onClickUpdateItem(item: IYwOauthClient) {
    setCurrentClientItem(item);
    setClientForm({
      ...item,
      remark: item.remark || '',
    });
  }

  function onClickSaveUpdateItem() {
    if (!currentClientItem) {
      show({
        type: 'DANGER',
        message: '保存修改失败',
      });
      return;
    }

    setClients([
      ...clients.filter((item) => item.clientId !== currentClientItem.clientId),
      {
        ...currentClientItem,
        ...clientForm,
      },
    ]);
  }

  function onClickRemoveItem(item: IYwOauthClient) {
    setClients([
      ...clients.filter((value) => value.clientId !== item.clientId),
    ]);
  }

  function onChangeForm(
    e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'showMenuEntry') {
      setForm({ ...form, showMenuEntry: value === 'true' });
      return;
    }

    setForm({ ...form, [name]: value });
  }

  function onChangeClientForm(
    e: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
  ) {
    const name = e.target.name;
    const value = e.target.value;

    if (name === 'enable') {
      setClientForm({ ...clientForm, enable: value === 'true' });
      return;
    }

    setClientForm({ ...clientForm, [name]: value });
  }

  async function onClickSave(e: FormEvent<HTMLFormElement>) {
    try {
      e.preventDefault();
      e.stopPropagation();

      const body = getFilterData(getDiffData(differenceData));
      if (isEmpty(body)) {
        show({
          type: 'SUCCESS',
          message: '保存完成',
        });
        return;
      }

      await updateOauthClientConfigMutation.mutateAsync({
        data: {
          ...body,
          ywClients: clients,
        },
      });

      clearData();
      show({
        type: 'SUCCESS',
        message: '保存完成',
      });
    } catch (e) {
      updateOauthClientConfigMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function clearData() {
    setDifferenceData([]);
  }

  return (
    <div className="row">
      <div className="col">
        <div className="vstack gap-4">
          <nav className="nav nav-pills flex-column flex-sm-row mb-4 mt-2">
            <a
              onClick={onClickTab.bind(this, 0)}
              className={classNames(
                'flex-sm-fill text-sm-center nav-link cursor-pointer',
                tabIndex === 0 ? 'bg-light' : false,
              )}
            >
              基本
            </a>
            <a
              onClick={onClickTab.bind(this, 1)}
              className={classNames(
                'flex-sm-fill text-sm-center nav-link cursor-pointer',
                tabIndex === 1 ? 'bg-light' : false,
              )}
            >
              列表
            </a>
          </nav>

          {tabIndex === 0 && (
            <form onSubmit={onClickSave} className="vstack gap-4">
              <div>
                <label className="form-label">显示菜单入口</label>
                <select
                  name="showMenuEntry"
                  value={form.showMenuEntry ? 'true' : 'false'}
                  onChange={onChangeForm}
                  className="form-select"
                  aria-label="showMenuEntry"
                  placeholder="请选择是否显示菜单入口"
                >
                  <option value="true">true</option>
                  <option value="false">false</option>
                </select>
              </div>

              <div>
                <label className="form-label">接入文档</label>
                <textarea
                  rows={1}
                  className="form-control"
                  name="doc"
                  value={form.doc}
                  onChange={onChangeForm}
                  aria-describedby="doc"
                  placeholder="请输入接入文档地址"
                />
              </div>

              <button
                type="submit"
                disabled={updateOauthClientConfigMutation.isLoading}
                className="btn btn-success w-25 my-4"
              >
                {updateOauthClientConfigMutation.isLoading && (
                  <span
                    className="spinner-border spinner-border-sm me-2"
                    role="status"
                    aria-hidden="true"
                  ></span>
                )}
                更新
              </button>
            </form>
          )}

          {tabIndex === 1 && (
            <form onSubmit={onClickSave} className="vstack gap-4">
              <div className="table-responsive">
                <table className="table table-hover align-middle">
                  <thead>
                    <tr className="text-nowrap">
                      <th className="fw-normal" scope="col">
                        enable
                      </th>
                      <th className="fw-normal" scope="col">
                        clientId
                      </th>
                      <th className="fw-normal" scope="col">
                        clientSecret
                      </th>
                      <th className="fw-normal" scope="col">
                        scope
                      </th>
                      <th className="fw-normal" scope="col">
                        state
                      </th>
                      <th
                        className="fw-normal"
                        scope="col"
                        style={{ width: 200 }}
                      ></th>
                    </tr>
                  </thead>
                  <tbody>
                    {clients.map((item) => {
                      return (
                        <tr
                          key={item.clientId}
                          className={classNames(
                            item.clientId === currentClientItem?.clientId
                              ? 'active'
                              : false,
                          )}
                        >
                          <td className="text-nowrap">{item.enable + ''}</td>
                          <th className="text-nowrap" scope="row">
                            {item.clientId}
                          </th>
                          <td className="text-nowrap">{item.clientSecret}</td>
                          <td className="text-nowrap">{item.scope}</td>
                          <td className="text-nowrap">{item.state}</td>
                          <td className="text-nowrap hstack gap-4">
                            <button
                              onClick={onClickUpdateItem.bind(this, item)}
                              type="button"
                              className="btn btn-primary btn-sm"
                            >
                              <i className="bi bi-pencil-square me-2"></i>
                              修改
                            </button>
                            <button
                              onClick={onClickRemoveItem.bind(this, item)}
                              type="button"
                              className="btn btn-danger btn-sm"
                            >
                              <i className="bi bi-trash me-2"></i>
                              删除
                            </button>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>

              {clients.length === 0 && (
                <div className="text-muted">暂无配置</div>
              )}

              <div className="card">
                <div className="card-body">
                  <div className="vstack gap-4">
                    <div>
                      <label className="form-label">enable</label>
                      <select
                        name="enable"
                        value={clientForm.enable ? 'true' : 'false'}
                        onChange={onChangeClientForm}
                        className="form-select"
                        aria-label="enable"
                        placeholder="请选择是否启用"
                      >
                        <option value="true">true</option>
                        <option value="false">false</option>
                      </select>
                    </div>

                    <div>
                      <label className="form-label">clientId</label>
                      <input
                        type="text"
                        className="form-control"
                        name="clientId"
                        value={clientForm.clientId}
                        onChange={onChangeClientForm}
                        aria-describedby="clientId"
                        placeholder="请输入客户端 Id（唯一标识）"
                      />
                    </div>

                    <div>
                      <label className="form-label"></label>
                      <input
                        type="text"
                        className="form-control"
                        name="clientSecret"
                        value={clientForm.clientSecret}
                        onChange={onChangeClientForm}
                        aria-describedby="clientSecret"
                        placeholder="请输入客户端 Secret（为空默认生成随机密钥）"
                      />
                    </div>

                    <div>
                      <label className="form-label">redirectUri</label>
                      <textarea
                        rows={1}
                        className="form-control"
                        name="redirectUri"
                        value={clientForm.redirectUri}
                        onChange={onChangeClientForm}
                        aria-describedby="redirectUri"
                        placeholder="请输入重定向地址"
                      />
                    </div>

                    <div>
                      <label className="form-label">scope</label>
                      <textarea
                        rows={1}
                        className="form-control"
                        name="scope"
                        value={clientForm.scope}
                        onChange={onChangeClientForm}
                        aria-describedby="scope"
                        placeholder="请输入权限范围（使用英文逗号分割），为空默认为 getUserInfo"
                      />
                    </div>

                    <div>
                      <label className="form-label">state</label>
                      <input
                        type="text"
                        className="form-control"
                        name="state"
                        value={clientForm.state}
                        onChange={onChangeClientForm}
                        aria-describedby="state"
                        placeholder="请输入状态（可以是任意值，为空默认生成状态）"
                      />
                    </div>

                    <div>
                      <label className="form-label">clientName</label>
                      <input
                        type="text"
                        className="form-control"
                        name="clientName"
                        value={clientForm.clientName}
                        onChange={onChangeClientForm}
                        aria-describedby="clientName"
                        placeholder="请输入客户端名称"
                      />
                    </div>

                    <div>
                      <label className="form-label">clientSite</label>
                      <textarea
                        rows={1}
                        className="form-control"
                        name="clientSite"
                        value={clientForm.clientSite}
                        onChange={onChangeClientForm}
                        aria-describedby="clientSite"
                        placeholder="请输入客户端站点地址"
                      />
                    </div>

                    <div>
                      <label className="form-label">clientLogo</label>
                      <textarea
                        rows={1}
                        className="form-control"
                        name="clientLogo"
                        value={clientForm.clientLogo}
                        onChange={onChangeClientForm}
                        aria-describedby="clientLogo"
                        placeholder="请输入客户端图标地址，建议图标比例为 1/1，例如 128x128、256x256 等"
                      />
                    </div>

                    <div>
                      <label className="form-label">imagePathPrefix</label>
                      <input
                        type="text"
                        className="form-control"
                        name="imagePathPrefix"
                        value={clientForm.imagePathPrefix}
                        onChange={onChangeClientForm}
                        aria-describedby="imagePathPrefix"
                        placeholder="请输入图片路径前缀"
                      />
                    </div>

                    <div>
                      <label className="form-label">remark</label>
                      <textarea
                        rows={1}
                        className="form-control"
                        name="remark"
                        value={clientForm.remark}
                        onChange={onChangeClientForm}
                        aria-describedby="remark"
                        placeholder="请输入备注"
                      />
                    </div>

                    <div>
                      {currentClientItem ? (
                        <button
                          onClick={onClickSaveUpdateItem}
                          type="button"
                          className="btn my-4 btn-primary"
                        >
                          <i className="bi bi-save2 me-2"></i>
                          保存修改
                        </button>
                      ) : (
                        <button
                          onClick={onClickSaveItem}
                          type="button"
                          className="btn my-4 btn-primary"
                        >
                          <i className="bi bi-plus-lg me-2"></i>
                          添加
                        </button>
                      )}
                    </div>
                  </div>
                </div>
              </div>

              <button
                type="submit"
                disabled={updateOauthClientConfigMutation.isLoading}
                className="btn btn-success w-25 my-4"
              >
                {updateOauthClientConfigMutation.isLoading && (
                  <span
                    className="spinner-border spinner-border-sm me-2"
                    role="status"
                    aria-hidden="true"
                  ></span>
                )}
                更新
              </button>
            </form>
          )}
        </div>
      </div>
    </div>
  );
}
